using System;
using System.Collections.Generic;
using Adoor.Expression.AST; 

namespace Adoor.Expression.AST
{
	/// <summary>
	/// Summary description for SetExpression.
	/// </summary>
	public class SetExpression
	{
		public SetExpression(ExpressionName setExp, ExpressionNode expVal, SetExpressionModes mode)
		{
			this.setExp = setExp;
			this.expVal = expVal;
			this.setExpressionMode = mode;
		}

		private ExpressionName setExp;
		private ExpressionNode expVal;
		private SetExpressionModes setExpressionMode;

		public ExpressionName SetExpressionName
		{
			get{ return setExp; }
			set{ setExp = value; }
		}

		public ExpressionNode ValueExpression
		{
			get{ return expVal; }
		}

		public SetExpressionModes SetExpressionMode
		{
			get{ return setExpressionMode; }
		}

		public static SetExpression[] ParseSetExpressions(Scanner scanner, ExpressionParser parser)
		{
            List<SetExpression> list = new List<SetExpression>();
			do
			{
				scanner.Scan();
				list.Add(SetExpression.ParseSetExpression(scanner, parser));
			} while(scanner.Token == ScannerToken.Comma);
			return list.ToArray();
		}

		public static SetExpression ParseSetExpression(Scanner scanner, ExpressionParser parser)
		{
			ExpressionParser ep = parser;
			
			if(scanner.Token != ScannerToken.Name)
				throw new Exception("Name expected");

			string name = scanner.GetString();
			scanner.Scan();
			ExpressionName enSet = null;
			
			if (scanner.Token == ScannerToken.Period)
			{
				scanner.Scan();
				if (scanner.Token != ScannerToken.Name)
					throw new Exception("name expected");
				string value = scanner.GetString();
				scanner.Scan();
				enSet = new ExpressionName(name, value);
			}
			else
				enSet = new ExpressionName("", name);

			SetExpressionModes mode = SetExpressionModes.Assign;
			if(scanner.Token == ScannerToken.MinusSign)
			{
				mode = SetExpressionModes.Remove;
				scanner.Scan();
			}
			else if (scanner.Token == ScannerToken.PlusSign)
			{
				mode = SetExpressionModes.Add;
				scanner.Scan();
			}

			if(scanner.Token != ScannerToken.Eq)
				throw new Exception("'=' Expected");

			scanner.Scan();

			ExpressionNode expr = ep.ParseRowValueConstructor(scanner);
			return new SetExpression(enSet, expr, mode);
		}
	}

	public enum SetExpressionModes
	{
		Assign,
		Add,
		Remove
	}
}
